/*
 Using strictkly file system to store data and retrieve.
 Directory Names = Fields Name
 Files Directories contain data or meta data - metadata.obj, data.obj
 
 Structure:
  - DATABASENAME
 -- TABLENAME
 --- COLUMNS
 ---- COLUMNNAME
 ----- datatype {an actual file}
 --- ROWS
 ---- ROWKEY {actual directory name}
 ----- COLUMNNAME
 ------ data {an actual file}
 
 SECURITY is stored in MASTER database - created in constructor of DataSystem class
 - USERS {table}
 - SECURITY {table}
 -- COLUMNS
 --- USERID
 --- DATABASENAME
 --- TABLENAME
 --- PERMISSIONS {r,w,d,a} r=read, w=write, d=delete, a=all
  
 To implement security, DataSystem constructor must have an override to include UserID and Password along with data storage path location.
 Then it must be called on every read, delete, write
  
 Required classes:
 - Constructor with input pointing to data directory containing databases
 - Set Data Function by DATABASENAME, COLOUMNNAME, ROWKEY, data, datatype_enum - also creates DATABASE + COLOUMNNAME and retries data saving using timer.
 - Get Data Function by DATABASENAME, COLOUMNNAME, ROWKEY, - several funcs one per datatype
 */

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Data;

namespace Gigaframe
{
    public class DataSystem
    {
        string _Error = "";
        string _DataFolderPath = AppDomain.CurrentDomain.BaseDirectory + "\\data";
        string _UserID = "ADMINISTRATOR";
        string _Password = "ADMINISTRATOR";

        public enum DataTypes
        { 
            Text,
            Binary
        }

        public enum PermissionTypes
        {
            Read,
            Write,
            Delete,
            Deny,
            All
        }

        public string Error
        {
            get { return _Error; }
        }

        /// <summary>
        /// Constructor with input pointing to data directory containing databases
        /// </summary>
        /// <param name="DataFolderPath"></param>
        public DataSystem(string DataFolderPath)
        {
            _DataFolderPath = DataFolderPath;
            
            InitDataSystem();
        }

        /// <summary>
        /// Constructor with input pointing to data directory containing databases & providing login information
        /// </summary>
        /// <param name="DataFolderPath"></param>
        /// <param name="UserID"></param>
        /// <param name="Password"></param>
        public DataSystem(string DataFolderPath, string UserID, string Password)
        {
            _DataFolderPath = DataFolderPath;
            _UserID = UserID;
            _Password = Password;

            InitDataSystem();
        }

        public void InitDataSystem()
        {
            //Create Master Database
            CreateDatabase("MASTER");

            //Add Administrator USER
            if (((string)GetData("MASTER", "USERS", "ADMINISTRATOR", "USERID")) == null)
            {
                //Set Administrator Account
                SetDataInternal("MASTER", "USERS", "ADMINISTRATOR", "USERID", "ADMINISTRATOR", DataTypes.Text);
                SetDataInternal("MASTER", "USERS", "ADMINISTRATOR", "PASSWORD", "ADMINISTRATOR", DataTypes.Text);
                SetDataInternal("MASTER", "USERS", "ADMINISTRATOR", "ACTIVE", "true", DataTypes.Text);

                //Create Sceurity Table
                CreateTable("MASTER", "SECURITY");

                //Create Columns so they're in the meta database structure
                CreateColumn("MASTER", "SECURITY", "USERID", DataTypes.Text);
                CreateColumn("MASTER", "SECURITY", "DATABASENAME", DataTypes.Text);
                CreateColumn("MASTER", "SECURITY", "TABLENAME", DataTypes.Text);
                CreateColumn("MASTER", "SECURITY", "PERMISSIONS", DataTypes.Text);
                
                //Setting initial data structure
                SetDataInternal("MASTER", "SECURITY", "ADMINISTRATOR", "USERID", "ADMINISTRATOR", DataTypes.Text);
                SetDataInternal("MASTER", "SECURITY", "ADMINISTRATOR", "PERMISSIONS", "a", DataTypes.Text); //for all
            }

            //Init Indexing Thread
            //Store Index in Memory
        }

        private bool CreateDirectory(string FolderPath)
        {
            bool retval = true;

            try
            {
                string[] arr_FolderPath = FolderPath.Split("\\".ToCharArray());
                string t_folderpath = "";

                if (!System.IO.Directory.Exists(FolderPath))
                {
                    for (int i = 0; i < arr_FolderPath.Length; i++)
                    {
                        if(i>0)
                            t_folderpath += ((arr_FolderPath[i].IndexOf(":") < 0)? "\\": "") +  arr_FolderPath[i];
                        else
                            t_folderpath += ((arr_FolderPath[i].IndexOf(":") < 0) ? "" : "") + arr_FolderPath[i];

                        if (arr_FolderPath[i].IndexOf(":") < 0)
                        {
                            if (!System.IO.Directory.Exists(t_folderpath))
                            {
                                System.IO.Directory.CreateDirectory(t_folderpath);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _Error = ex.ToString();

                retval = false;
            }

            return retval;
        }

        private bool DeleteDirectory(string FolderPath)
        {
            bool retval = true;

            try
            {
                if (System.IO.Directory.Exists(FolderPath))
                {
                    System.IO.Directory.Delete(FolderPath);
                }
            }
            catch (Exception ex)
            {
                _Error = ex.ToString();

                retval = false;
            }

            return retval;
        }

        public bool CreateDatabase(string DatabaseName)
        {
            bool retval = true;

            if (!System.IO.Directory.Exists(_DataFolderPath + "\\" + DatabaseName))
                CreateDirectory(_DataFolderPath + "\\" + DatabaseName);
            
            return retval;
        }

        public bool CreateTable(string DatabaseName, string TableName)
        {
            bool retval = true;

            CreateDatabase(DatabaseName);

            if (!System.IO.Directory.Exists(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName))
                CreateDirectory(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName);

            if (!System.IO.Directory.Exists(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\columns"))
                CreateDirectory(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\columns");

            if (!System.IO.Directory.Exists(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\rows"))
                CreateDirectory(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\rows");

            if (!System.IO.Directory.Exists(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\index"))
                CreateDirectory(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\index");

            if (!System.IO.Directory.Exists(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\flags"))
                CreateDirectory(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\flags");

            return retval;
        }

        public bool CreateColumn(string DatabaseName, string TableName, string ColumnName, DataTypes DataType)
        {
            bool retval = true;

            CreateDatabase(DatabaseName);

            CreateTable(DatabaseName, TableName);

            if (!System.IO.Directory.Exists(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\columns\\" + ColumnName))
            {
                CreateDirectory(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\columns\\" + ColumnName);
                System.IO.File.WriteAllText(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\columns\\" + ColumnName + "\\datatype", DataType.ToString());
            }

            return retval;
        }

        public bool SetData(string DatabaseName, string TableName, string RowKey, string ColumnName, object data, DataTypes datatype)
        {
            bool retval = true;
            
            if (CheckPermissions(DatabaseName, TableName, PermissionTypes.Write))
            {
                if (!SetDataInternal(DatabaseName, TableName, RowKey, ColumnName, data, datatype))
                {
                    retval = false;
                }
            }
            else
            {
                _Error = "WRITE ACCESS DENIED!";
            }

            return retval;
        }

        public Guid SetData(string DatabaseName, string TableName, string ColumnName, object data, DataTypes datatype)
        {
            Guid retval = Guid.NewGuid();

            if (CheckPermissions(DatabaseName, TableName, PermissionTypes.Write))
            {
                if (!SetDataInternal(DatabaseName, TableName, retval.ToString(), ColumnName, data, datatype))
                {
                    retval = Guid.Empty;
                }
            }
            else
            {
                _Error = "WRITE ACCESS DENIED!";
            }

            return retval;
        }

        private Guid SetDataInternal(string DatabaseName, string TableName, string ColumnName, object data, DataTypes datatype)
        {
            Guid retval = Guid.NewGuid();

            if (!SetDataInternal(DatabaseName, TableName, retval.ToString(), ColumnName, data, datatype))
            {
                retval = Guid.Empty;
            }

            return retval;
        }

        private bool SetDataInternal(string DatabaseName, string TableName, string RowKey, string ColumnName, object data, DataTypes DataType)
        {
            bool retval = true;

                try
                {
                    CreateDatabase(DatabaseName);
                    CreateTable(DatabaseName, TableName);
                    CreateColumn(DatabaseName, TableName, ColumnName, DataType);

                    //If not create it

                    CreateDirectory(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\rows\\" + RowKey);
                    CreateDirectory(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\rows\\" + RowKey + "\\" + ColumnName);

                    //if (!System.IO.File.Exists(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\rows\\" + RowKey + "\\" + ColumnName + "\\data"))
                    //    System.IO.File.Create(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\rows\\" + RowKey + "\\" + ColumnName + "\\data");

                    if (DataType == DataTypes.Binary)
                        System.IO.File.WriteAllBytes(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\rows\\" + RowKey + "\\" + ColumnName + "\\data", (byte[])data);
                    else if (DataType == DataTypes.Text)
                        System.IO.File.WriteAllText(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\rows\\" + RowKey + "\\" + ColumnName + "\\data", (string)data);
                }
                catch (Exception ex)
                {
                    retval = false;
                    _Error = ex.ToString();
                }

            return retval;
        }

        public bool DeleteDataRecord(string DatabaseName, string TableName, string RowKey)
        {
            if (CheckPermissions(DatabaseName, TableName, PermissionTypes.Delete))
            {
                return DeleteDataRecordInternal(DatabaseName, TableName, RowKey);
            }
            else
                return false;
        }

        private bool DeleteDataRecordInternal(string DatabaseName, string TableName, string RowKey)
        {
            bool retval = true;
            string delpath = "";

            try
            {
                delpath = _DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\rows\\" + RowKey;

                if (DeleteDirectory(delpath))
                { 
                    //failed deleting
                }
            }
            catch (Exception ex)
            {
                retval = false;
                _Error = ex.ToString();
            }

            return retval;
        }

        private object GetDataInternal(string DatabaseName, string TableName, string RowKey, string ColumnName)
        {
            object retval = null;
            string datatype = DataTypes.Text.ToString();

            
                try
                {
                    CreateDatabase(DatabaseName);
                    CreateTable(DatabaseName, TableName);
                    CreateColumn(DatabaseName, TableName, ColumnName, DataTypes.Text);

                    //Get DataType
                    datatype = System.IO.File.ReadAllText(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\columns\\" + ColumnName + "\\datatype");

                    if (datatype == DataTypes.Binary.ToString())
                    {
                        try
                        {
                            retval = System.IO.File.ReadAllBytes(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\rows\\" + RowKey + "\\" + ColumnName + "\\data");
                        }
                        catch (Exception exBinary)
                        {
                            retval = null;
                        }
                    }
                    else if (datatype == DataTypes.Text.ToString())
                    {
                        try
                        {
                            retval = System.IO.File.ReadAllText(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\rows\\" + RowKey + "\\" + ColumnName + "\\data");
                        }
                        catch (Exception exText)
                        {
                            retval = null;
                        }
                    }

                    try
                    {
                        if (retval != null)
                            System.IO.File.Create(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\flags\\update_index");
                    }
                    catch(Exception ex1)
                    {
                        _Error = ex1.ToString();
                    }
                }
                catch (Exception ex)
                {
                    _Error = ex.ToString();
                    retval = null;
                }

            return retval;
        }

        public object GetData(string DatabaseName, string TableName, string RowKey, string ColumnName)
        {
            object retval = null;
            string datatype = DataTypes.Text.ToString();
            
            if (CheckPermissions(DatabaseName, TableName, PermissionTypes.Read))
            {
                retval = GetDataInternal(DatabaseName, TableName, RowKey, ColumnName);
            }
            else 
            {
                _Error = "READ ACCESS DENIED!";
            }

            return retval;
        }

        private DataTable GetDataTableInternal(string DatabaseName, string TableName, string WhereClause, string SortClause)
        {
            DataTable retval = new DataTable();
            int i, j, k;
            string datatype = DataTypes.Text.ToString();
            string dataText = "";
            byte[] dataBinary = null;
            System.IO.DirectoryInfo diRow = null;
            System.IO.DirectoryInfo di = null;
            DataRow dr = null;

            
                try
                {

                    CreateDatabase(DatabaseName);
                    CreateTable(DatabaseName, TableName);

                    if (true || !System.IO.File.Exists(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\index\\index.xml") ||
                        System.IO.File.Exists(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\flags\\update_index"))
                    {

                        //Parse Where Clause into If Statements.
                        // OR Read Entire Database Table into DataTable and use Where clause there. 

                        //Columns
                        string[] columns = System.IO.Directory.GetDirectories(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\columns");
                        retval.Columns.Add("RowKey", Type.GetType("System.String"));
                        for (i = 0; i < columns.Length; i++)
                        {
                            //get datatype
                            di = new System.IO.DirectoryInfo(columns[i]);
                            datatype = System.IO.File.ReadAllText(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\columns\\" + di.Name + "\\datatype");

                            if (datatype == DataTypes.Binary.ToString())
                                retval.Columns.Add(di.Name, Type.GetType("System.Byte[]"));
                            else if (datatype == DataTypes.Text.ToString())
                                retval.Columns.Add(di.Name, Type.GetType("System.String"));

                        }

                        //Rows
                        string[] rows = System.IO.Directory.GetDirectories(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\rows");

                        for (j = 0; j < rows.Length; j++)
                        {
                            diRow = new System.IO.DirectoryInfo(rows[j]);

                            dr = retval.NewRow();

                            dr["RowKey"] = diRow.Name;

                            for (i = 0; i < columns.Length; i++)
                            {
                                di = new System.IO.DirectoryInfo(columns[i]);

                                //get datatype
                                datatype = System.IO.File.ReadAllText(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\columns\\" + di.Name + "\\datatype");

                                if (datatype == DataTypes.Binary.ToString())
                                {
                                    if (System.IO.File.Exists(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\rows\\" + diRow.Name + "\\" + di.Name + "\\data"))
                                        dataBinary = System.IO.File.ReadAllBytes(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\rows\\" + diRow.Name + "\\" + di.Name + "\\data");
                                    else
                                        dataBinary = null;
                                    dr[di.Name] = dataBinary;
                                }
                                else if (datatype == DataTypes.Text.ToString())
                                {
                                    if (System.IO.File.Exists(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\rows\\" + diRow.Name + "\\" + di.Name + "\\data"))
                                        dataText = System.IO.File.ReadAllText(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\rows\\" + diRow.Name + "\\" + di.Name + "\\data");
                                    else
                                        dataText = null;
                                    dr[di.Name] = dataText;
                                }

                            }

                            retval.Rows.Add(dr);
                        }

                        //Save Index
                        DataSet ds = new DataSet(DatabaseName);
                        ds.Tables.Add(retval);

                        ds.WriteXml(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\index\\index.xml");

                        //Delete Flag
                        try
                        {
                            System.IO.File.Delete(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\flags\\update_index");
                        }
                        catch (Exception ex1)
                        {
                            _Error = ex1.ToString();

                            //Failed to delete flag!
                        }
                    }
                    else 
                    { 
                        //Get Index Data from index.xml file
                        DataSet dsGet = new DataSet(DatabaseName);
                        dsGet.ReadXml(_DataFolderPath + "\\" + DatabaseName + "\\" + TableName + "\\index\\index.xml");

                        if (dsGet.Tables.Count > 0)
                            retval = dsGet.Tables[0];
                    }

                    DataTable dt = DataTableQuery(retval, WhereClause, SortClause);

                    retval = dt;

                }
                catch (Exception ex)
                {
                    _Error = ex.ToString();
                    retval = null;
                }
            
            return retval;
        }

        public DataTable GetDataTable(string DatabaseName, string TableName, string WhereClause, string SortClause)
        {
            DataTable retval = new DataTable();
            
            if (CheckPermissions(DatabaseName, TableName, PermissionTypes.Read))
            {
                retval = GetDataTableInternal(DatabaseName, TableName, WhereClause, SortClause);
            }
            else
            {
                _Error = "READ ACCESS DENIED!";
            }
            

            return retval;
        }


        public static DataTable DataTableQuery(DataTable inDataTable, string Query, string Sort)
        {
            int i = 0;

            //Do Some Weeding
            System.Data.DataRow[] drs = null;
            if (Sort != "")
            {
                drs = inDataTable.Select(Query, Sort);
            }
            else
            {
                drs = inDataTable.Select(Query);
            }
            System.Data.DataTable dtr = new System.Data.DataTable();
            dtr = inDataTable.Clone();

            for (i = 0; i < drs.Length; i++)
            {
                dtr.ImportRow(drs[i]);
            }

            return dtr;
        }

        public bool CheckPermissions(string DatabaseName, string TableName, PermissionTypes PermissionType)
        {
            bool retval = false;
            DataTable dt = null;

            if (((string)GetDataInternal("MASTER", "USERS", _UserID, "PASSWORD")) != null)
            {
                if (((string)GetDataInternal("MASTER", "USERS", _UserID, "PASSWORD")) == _Password)
                {
                    //DataSystem Level
                    if (retval == false)
                    {
                        dt = GetDataTableInternal("MASTER", "SECURITY", "USERID='" + _UserID + "' AND ((DATABASENAME='' AND TABLENAME='') OR (DATABASENAME IS NULL AND TABLENAME IS NULL))", "");

                        //Check Database Level
                        if (dt.Rows[0]["PERMISSIONS"] != null)
                        {
                            if (PermissionType == PermissionTypes.Read)
                                if (dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("r") >= 0 ||
                                    dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("a") >= 0)
                                {
                                    retval = true;
                                }

                            if (PermissionType == PermissionTypes.Write)
                                if (dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("w") >= 0 ||
                                    dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("a") >= 0)
                                {
                                    retval = true;
                                }

                            if (PermissionType == PermissionTypes.Delete)
                                if (dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("d") >= 0 ||
                                    dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("a") >= 0)
                                {
                                    retval = true;
                                }

                            if (PermissionType == PermissionTypes.All)
                                if (dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("a") >= 0)
                                {
                                    retval = true;
                                }
                        }
                    }


                    //Database Level
                    if (retval == false)
                    {
                        dt = GetDataTable("MASTER", "SECURITY", "USERID='" + _UserID + "' AND DATABASENAME='" + DatabaseName + "'", "");

                        //Check Database Level
                        if (dt.Rows[0]["PERMISSIONS"] != null)
                        {
                            if (PermissionType == PermissionTypes.Read)
                                if (dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("r") >= 0 ||
                                    dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("a") >= 0)
                                {
                                    retval = true;
                                }

                            if (PermissionType == PermissionTypes.Write)
                                if (dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("w") >= 0 ||
                                    dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("a") >= 0)
                                {
                                    retval = true;
                                }

                            if (PermissionType == PermissionTypes.Delete)
                                if (dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("d") >= 0 ||
                                    dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("a") >= 0)
                                {
                                    retval = true;
                                }

                            if (PermissionType == PermissionTypes.All)
                                if (dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("a") >= 0)
                                {
                                    retval = true;
                                }
                        }
                    }

                    //Table Level
                    if (retval == false)
                    {
                        dt = GetDataTable("MASTER", "SECURITY", "USERID='" + _UserID + "' AND DATABASENAME='" + DatabaseName + "' AND TABLENAME='" + TableName + "'", "");

                        //Check Database Level
                        if (dt.Rows[0]["PERMISSIONS"] != null)
                        {
                            if (PermissionType == PermissionTypes.Read)
                                if (dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("r") >= 0 ||
                                    dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("a") >= 0)
                                {
                                    retval = true;
                                }

                            if (PermissionType == PermissionTypes.Write)
                                if (dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("w") >= 0 ||
                                    dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("a") >= 0)
                                {
                                    retval = true;
                                }

                            if (PermissionType == PermissionTypes.Delete)
                                if (dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("d") >= 0 ||
                                    dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("a") >= 0)
                                {
                                    retval = true;
                                }

                            if (PermissionType == PermissionTypes.All)
                                if (dt.Rows[0]["PERMISSIONS"].ToString().IndexOf("a") >= 0)
                                {
                                    retval = true;
                                }
                        }
                    }
                }
            }

            return retval;
        }

        public System.Web.UI.WebControls.TreeNode GetDataSystemSchema()
        {
            int i, j, k = 0;
            System.Web.UI.WebControls.TreeNode n = null;
            System.Web.UI.WebControls.TreeNode tn = null;
            System.Web.UI.WebControls.TreeNode ntable = null;
            System.Web.UI.WebControls.TreeNode ncol = new System.Web.UI.WebControls.TreeNode("columns");
            System.Web.UI.WebControls.TreeNode nrow = new System.Web.UI.WebControls.TreeNode("rows");
            string[] databases = null;
            string[] tables = null;
            string[] columns = null;
            string[] rows = null;
            System.IO.FileInfo fi = null;
            System.IO.FileInfo fi2 = null;
            System.IO.FileInfo fi3 = null;

            System.Web.UI.WebControls.TreeNode retval = new System.Web.UI.WebControls.TreeNode();

            databases = System.IO.Directory.GetDirectories(_DataFolderPath);

            for (i = 0; i < databases.Length; i++)
            {
                fi = new System.IO.FileInfo(databases[i]);
                n = new System.Web.UI.WebControls.TreeNode();
                n.Text = fi.Name;
                n.Value = "DATABASE=" + fi.Name;

                //Tables
                tables = System.IO.Directory.GetDirectories(databases[i]);
                
                
                for(j = 0; j < tables.Length; j++)
                {
                    fi2 = new System.IO.FileInfo(tables[j]);
                    ntable = new System.Web.UI.WebControls.TreeNode();
                    ntable.Text = fi2.Name;
                    ntable.Value = "DATABASE=" + fi.Name + "&TABLE=" + fi2.Name;

                    //Columns
                    ncol = new System.Web.UI.WebControls.TreeNode("columns");
                    columns = System.IO.Directory.GetDirectories(tables[j] + "\\columns");

                    for (k = 0; k < columns.Length; k++)
                    {
                        fi3 = new System.IO.FileInfo(columns[k]);
                        tn = new System.Web.UI.WebControls.TreeNode();
                        tn.Text = fi3.Name;
                        tn.Value = "DATABASE=" + fi.Name + "&TABLE=" + fi2.Name + "&COLUMN=" + fi3.Name;

                        ncol.ChildNodes.Add(tn);
                    }
                    ntable.ChildNodes.Add(ncol);

                    //Rows
                    nrow = new System.Web.UI.WebControls.TreeNode("rows");
                    rows = System.IO.Directory.GetDirectories(tables[j] + "\\rows");

                    System.Web.UI.WebControls.TreeNode ncol2 = null;
                    for (k = 0; k < rows.Length; k++)
                    {
                        fi3 = new System.IO.FileInfo(rows[k]);
                        tn = new System.Web.UI.WebControls.TreeNode();
                        tn.Text = fi3.Name;
                        tn.Value = "DATABASE=" + fi.Name + "&TABLE=" + fi2.Name + "&ROWKEY=" + fi3.Name;

                        nrow.ChildNodes.Add(tn);
                    }
                    ntable.ChildNodes.Add(nrow);

                    n.ChildNodes.Add(ntable);
                }

                //Add it to parent
                retval.ChildNodes.Add(n);
            }

            return retval;
        }

        public static ArrayList ParseSelectedSchemaNode(string nodevalue)
        {
            ArrayList retval = new ArrayList();
            int i = 0;
            string[] t_params = nodevalue.Split("&".ToCharArray());
            string[] t_params1 = null;

            for (i = 0; i < t_params.Length; i++)
            {
                if (t_params[i].IndexOf("=") >= 0)
                {
                    t_params1 = t_params[i].Split("=".ToCharArray());

                    retval.Add(t_params1[1]);
                }
            }

            return retval;
        }
    }
}
